package cn.itcast.zt.order;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

/**
 * @author zhangtian105
 * @ClassName BeanOrderConfiguration.java
 * @projectName SpringBoot2.x
 * @Description
 *      @DependsOn注解可以用来控制bean的创建顺序，该注解用于声明当前bean依赖于另外一个bean
 *      所依赖的bean会被容器确保在当前bean实例化之前被实例化
 *
 * @DependsOn的使用：
 *      直接或者间接标注在带有@Component注解的类上面;
 *      直接或者间接标注在带有@Bean注解的方法上面;
 *      使用@DependsOn注解到类层面仅仅在使用 component-scanning 方式时才有效，如果带有@DependsOn注解的类通过XML方式使用，该注解会被忽略，<bean depends-on="..."/>这种方式会生效。
 * 参数注入
 * 在@Bean标注的方法上，如果你传入了参数，springboot会自动会为这个参数在spring上下文里寻找这个类型的引用。并先初始化这个类的实例。
 * 利用此特性，我们也可以控制bean的加载顺序。
 * 如：
 *  @Bean
 *  public BeanA beanA(BeanB demoB){
 *      System.out.println("bean A init");
 *      return new BeanA();
 *  }
 *
 *  @Bean
 *  public BeanB beanB(){
 *      System.out.println("bean B init");
 *      return new BeanB();
 *  }
 *
 * 利用bean的生命周期中的扩展点也可以控制Bean加载顺序
 *
 * @AutoConfigureOrder
 *  这个注解用来指定配置文件的加载顺序。但是在实际测试中发现，以下这样使用是不生效的：
 *  @AutoConfigureOrder只能改变外部依赖的@Configuration的顺序。如何理解是外部依赖呢。
 *  能被你工程内部scan到的包，都是内部的Configuration，而spring引入外部的Configuration，都是通过spring特有的spi文件：spring.factories
 * @createTime 2020年11月10日 19:16:00
 */
@Configuration
public class BeanOrderConfiguration {
    @Bean
    // @Order(value = 1) // 无用
    @DependsOn(value = "beanC")
    public BeanA beanA() {
        System.out.println("BeanA......");
        return new BeanA() ;
    }

    @Bean
    // @Order(value = 3) // 无用
    public BeanB beanB() {
        System.out.println("BeanB......");
        return new BeanB() ;
    }

    @Bean
    // @Order(value = 2) // 无用
    @DependsOn(value = "beanB")
    public BeanC beanC() {
        System.out.println("BeanC......");
        return new BeanC() ;
    }
}
